#include "NodoIndice.h"
#include "RegistroIndice.h"


NodoIndice::NodoIndice() { }

NodoIndice::~NodoIndice() { }


unsigned int NodoIndice::serialize(char* &arrBytes){
	this->serInator.reset();

	// Una marca para saber donde empieza el bloque
	char firma = 'I';
	this->serInator.serializar(arrBytes, firma);

	// La cantidad de registros en el bloque
	unsigned short int cant = this->lRegistros.size();
	this->serInator.serializar(arrBytes, cant);

	// Uno a uno serializa los registros
	std::list<IRegistro*>::iterator it;
	for (it = this->lRegistros.begin(); it != this->lRegistros.end(); ++it){
		this->serInator.serializar(arrBytes, *it);
	}

	return this->serInator.getBufferSize();
}


void NodoIndice::deSerialize(char* arrBytes){
	// Primero limpia el nodo por si tiene algun dato y luego
	// inicializa el serializador
	this->clear();
	this->serInator.reset();

	// Una marca para saber donde empieza el bloque
	char firma = 'I';
	this->serInator.desSerializar(arrBytes, firma);

	// La cantidad de registros en el bloque
	unsigned short int cantElementos = 0;
	this->serInator.desSerializar(arrBytes, cantElementos);

	// Los elementos del Nodo
	for (int i=0; i< cantElementos; ++i){
		// Un nodo indice siempre contiene registros indice
		IRegistro* regTemp = new RegistroIndice();

		this->serInator.desSerializar(arrBytes, regTemp);
		this->lRegistros.push_back(regTemp);
	}
}


unsigned int NodoIndice::getSize() const{
	unsigned int tamDatos = this->getBytes();

	// Mas el tamaño de los metadatos
	unsigned int tamMeta = sizeof(char); // La marca de debug
	tamMeta += sizeof(unsigned short int);	// El contador de elementos

	return tamDatos + tamMeta;
}


// Devuelve un nuevo registro de tipo indice con la clave promovida
// La clave promovida es eliminada del nodo
IRegistro* NodoIndice::construirRegistroDivisor(INodo& n){
	/** En este caso hay que quitar del nodo de la izquierda ("this") la clave con el maximo valor.
	 * Al hacer "split" el nodo de la izquierda se queda sin el registro de conveniencia con
	 * el maximo valor imposible
	 * Hay que obtener la ultima clave de este nodo y reemplazarlo por el maximo de conveniencia.
	 * */

	// Ahora "rit" apunta al ultimo registro
	std::list<IRegistro*>::reverse_iterator rit = this->lRegistros.rbegin();

	// Un nuevo registro divisor
	RegistroIndice* rTemp = static_cast<RegistroIndice*>(*rit);
	RegistroIndice* rSeparador = new RegistroIndice(rTemp->getClave(), rTemp->getPosHijo());

	// Setea la clave maxima imposible
	rTemp->setClave(IRegistro::GET_MAXIMO_IMPOSIBLE());

	// Devuelve el nuevo registro con la clave que fue promovida
	return rSeparador;
}



